#include "driver_hardware.h"

static const int PERIOD_COUNT = 5999;

static inline float Constraint(float _val)
{
  if(_val > 1) _val = 1;
  else if(_val < 0) _val = 0;

  return _val;
}

void driver_ConfigTimerForPwm(void)
{
  // PIN8 W PIN_9 V PIN10 U
  gpio_init_type  gpio_init_struct = {0};
  tmr_output_config_type tmr_output_struct = { 0 };

  crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  gpio_default_para_init(&gpio_init_struct);
  gpio_init_struct.gpio_pins = GPIO_PINS_8 | GPIO_PINS_9 | GPIO_PINS_10;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init(GPIOA, &gpio_init_struct);

  // 32Khz
  tmr_base_init(TMR1, (192000000 / 32000) - 1, 0);
  tmr_cnt_dir_set(TMR1, TMR_COUNT_TWO_WAY_1);

  tmr_output_default_para_init(&tmr_output_struct);
  tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  tmr_output_struct.oc_output_state = TRUE;
  tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  tmr_output_struct.oc_idle_state = TRUE;
  tmr_output_struct.occ_output_state = FALSE;
  tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  tmr_output_struct.occ_idle_state = FALSE;

  /* channel 1 */
  tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
  tmr_output_channel_buffer_enable(TMR1, TMR_SELECT_CHANNEL_1, TRUE);

  /* channel 2 */
  tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
  tmr_output_channel_buffer_enable(TMR1, TMR_SELECT_CHANNEL_2, TRUE);

  /* channel 3 */
  tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
  tmr_output_channel_buffer_enable(TMR1, TMR_SELECT_CHANNEL_3, TRUE);

  /* channel 4 */
  // 低端采样
  tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B;
  tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_4, &tmr_output_struct);
  tmr_output_channel_buffer_enable(TMR1, TMR_SELECT_CHANNEL_4, TRUE);
  tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, PERIOD_COUNT - 1);

  tmr_repetition_counter_set(TMR1, 0x01);

  /* overflow interrupt enable */
//  tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);
//  nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0);

  driver_SetPwmDutyByRegister(0, 0, 0);

  /* output enable */
  tmr_output_enable(TMR1, TRUE);
  /* enable tmr1 */
  tmr_counter_enable(TMR1, TRUE);
}

void driver_SetPwmDutyByRegister(float _dutyA, float _dutyB, float _dutyC)
{
  _dutyA = Constraint(_dutyA);
  _dutyB = Constraint(_dutyB);
  _dutyC = Constraint(_dutyC);

  // U V W
  tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, (uint16_t)(_dutyA * PERIOD_COUNT));
  tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_2, (uint16_t)(_dutyB * PERIOD_COUNT));
  tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, (uint16_t)(_dutyC * PERIOD_COUNT));
}
